#include "EmulatorCompile.h"

Function *getCompilationUnit(void)
{
  // Create a new function and set the insertion point to the beginning of the
  // function. The function takes 1 paramater. the paramater is the base address
  // of the current emulated cpu.
  LLVMContext &Context = getGlobalContext();

  // Get the type of the function.
  FunctionType *FuncType = FunctionType::get(Type::getVoidTy(Context), 
                                             Type::getInt64Ty(Context), 
                                             false);

  // Get a function body for the current compilation unit.
  Function *newFunc = Function::Create(FuncType,
                                       Function::ExternalLinkage, 
                                       Twine::utohexstr(10),
                                       getGlobalModule());

  // Do not generate the prologue and epilogue.
  newFunc->addFnAttr(Attribute::Naked);

  // Create the first basicblock in this function.
  BasicBlock::Create(getGlobalContext(), newFunc->getName(), newFunc);

  return newFunc;
}

void generateInstructionIR(Function* current, void* s, void* e)
{
  bxInstruction_c* i = (bxInstruction_c*) s;
  bxInstruction_c* last = (bxInstruction_c*) e;

  getGlobalIRGen()->initializeIRGeneration(current);

  // it is possible that this is a outdated compilation request.
  if (s == e) 
  {
    // generate the return instruction.
    getGlobalIRGen()->generateEOBIR(current);
    return;
  }

  for(;;)
  {
    // dissasmble the instructions one by one to LLVM IR.
    getGlobalIRGen()->generateInstructionIR(i);
    if (++i == last) break;
  }

  // generate the return instruction.
  getGlobalIRGen()->generateEOBIR(current);
}

